<?php

namespace app;

use think\facade\Cache;

class LogHelper
{
    private static $instance;

    public static $level_info = 'info';
    public static $level_warning = 'warning';
    public static $level_error = 'error';

    /**
     * 本助手类基于我的docker包：https://hub.docker.com/r/dreamplay/log
     */
    public static function instance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new static();
        }
        return self::$instance;
    }

    /**
     * 获取access_token
     * Author:我只想看看蓝天<1207032539@qq.com>
     * @return array|bool|string
     */
    private function getLogAccessToken()
    {
        $key = 'LogHelper:getLogAccessToken';
        if (!empty($res = Cache::get($key))) {
            return $res;
        }
        $appid = config('app.common_log.appid');
        $appsecret = config('app.common_log.appsecret');
        $url = config('app.common_log.host') . config('app.common_log.api.getAccessToken');
        $param = [
            'appid' => $appid,
            'appsecret' => $appsecret,
        ];
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);//限时间，不能长期阻塞
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $param);
        $res = curl_exec($curl);
        curl_close($curl);
        $res = json_decode($res, true) ?: [];
        if (!empty($res['info']['access_token'])) {
            Cache::set($key, $res['info']['access_token'], $res['info']['expires_in'] - 60);
        }
        return $res['info']['access_token'] ?? '';
    }

    /**
     * 记录日志
     * @param mixed $level //日志等级或者日志数组
     * @param string $message //信息
     * @param string $other //其他信息
     * @param string $code //http状态码
     * @param float|int $waste_time //耗时（秒）
     * @param string $client_ip //客户端ip
     * @param string $url //接口
     * @param string $create_time //请求时间
     * @return bool
     * @author 我只想看看蓝天 <1207032539@qq.com>
     */
    public function saveLog(
        $level,
        string $message = '',
        string $other = '',
        string $code = '',
        float $waste_time = 0,
        string $client_ip = '',
        string $url = '',
        string $create_time = ''): bool
    {
        $data = [];
        if (is_array($level)) {
            foreach ($level as $item) {
                $data[] = [
                    'project_name' => config('app.common_log.app_name'),
                    'level' => $item['level'] ?? 'info',
                    'client_ip' => $item['client_ip'] ?? '0.0.0.0',
                    'server_ip' => config('app.common_log.server_ip'),
                    'message' => $item['message'] ?? '',
                    'other' => $item['other'] ?? '',
                    'create_time' => ($item['create_time'] ?? '') ?: date('Y-m-d H:i:s'),
                    'url' => $item['url'] ?? '',
                    'waste_time' => $item['waste_time'] ?? 0,
                    'code' => $item['code'] ?? 0,
                ];
            }
        } else {
            $data[] = [
                'project_name' => config('app.common_log.app_name'),
                'level' => $level,
                'client_ip' => $client_ip,
                'server_ip' => config('app.common_log.server_ip'),
                'message' => $message,
                'other' => $other,
                'create_time' => $create_time ?: date('Y-m-d H:i:s'),
                'url' => $url,
                'waste_time' => $waste_time,
                'code' => $code,
            ];
        }

        if (config('app.common_log.kafka_enable')) {
            $appid = config('app.common_log.appid');
            foreach ($data as $param) {
                $param['appid'] = $appid; //kafka需要指定推送账号
                KafkaHelper::instance(config('app.common_log.kafka_brokers'), config('app.common_log.kafka_topic'))->produce($param);
            }
            return true;
        } else {
            $post_data = [];
            $post_data['authorization'] = $this->getLogAccessToken();
            $post_data['data'] = $data;
            $url = config('app.common_log.host') . config('app.common_log.api.saveLog');
            $curl = curl_init($url);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_TIMEOUT, 10);//限时间，不能长期阻塞
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_HTTPHEADER, [
                'Content-type:application/json;charset=utf-8',
            ]);
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($post_data, 256));
            $res = curl_exec($curl);
            curl_close($curl);
            $res = json_decode($res, true) ?: [];
            if (isset($res['code']) && $res['code'] == 200) {
                return true;
            }
        }
        return false;
    }

    public function errorLog(string $message, string $other = '', string $code = '', float $waste_time = 0, string $client_ip = '', string $url = '', string $create_time = '')
    {
        return $this->saveLog('error', $message, $other, $code, $waste_time, $client_ip, $url, $create_time);
    }

    public function warningLog(string $message, string $other = '', string $code = '', float $waste_time = 0, string $client_ip = '', string $url = '', string $create_time = '')
    {
        return $this->saveLog('warning', $message, $other, $code, $waste_time, $client_ip, $url, $create_time);
    }

    public function infoLog(string $message, string $other = '', string $code = '', float $waste_time = 0, string $client_ip = '', string $url = '', string $create_time = '')
    {
        return $this->saveLog('info', $message, $other, $code, $waste_time, $client_ip, $url, $create_time);
    }

}
